/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bff.spi.defaultvalue;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.inspur.edp.bff.api.exception.BffFrameworkException;
import com.inspur.edp.bff.api.exception.ErrorCodes;
import com.inspur.edp.bff.api.manager.IFSManager;
import com.inspur.edp.bff.entity.defaultvalue.VoDefaultValue;
import com.inspur.edp.bff.spi.builtin.BffEntityResInfoImpl;
import com.inspur.edp.cef.spi.entity.info.propertyinfo.DataTypePropertyInfo;
import com.inspur.edp.cef.spi.entity.resourceInfo.ModelResInfo;
import com.inspur.edp.cef.spi.jsonser.base.StringUtils;

import java.io.IOException;
import java.lang.reflect.Method;

public class VoBuiltInDefaultValueDeserializer extends JsonDeserializer<VoDefaultValue> {

    protected IFSManager manager;

    public VoBuiltInDefaultValueDeserializer(IFSManager manager) {
        this.manager = manager;
    }


    @Override
    public VoDefaultValue deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException {
        VoDefaultValue voDefaultValue = new VoDefaultValue();

        if (jsonParser.getCurrentToken() != JsonToken.START_OBJECT) {
            throw new BffFrameworkException(ErrorCodes.BFF_FRAMEWORK_0001);
        }

        jsonParser.nextToken();
        while (jsonParser.getCurrentToken() == JsonToken.FIELD_NAME) {

            if (jsonParser.getCurrentToken() == JsonToken.END_OBJECT) {
                break;
            }
            String propertyName = jsonParser.getValueAsString();
            jsonParser.nextToken();
            BffEntityResInfoImpl resInfo = getCefEntityResInfo();
//            Map<String, DataTypePropertyInfo> map = resInfo.getEntityTypeInfo().getPropertyInfos();

//            Object value = map.get(getPropertyName(propertyName)).read(jsonParser, ctxt, null);
//            voDefaultValue.getDefaultValue().put(getPropertyName(propertyName), value);

            DataTypePropertyInfo info = resInfo.getEntityTypeInfo().getPropertyInfo(propertyName);
            if (info == null) {
                String entityCode = resInfo.getEntityCode();
                String[] messageParams = new String[]{entityCode, propertyName};
                throw new BffFrameworkException(ErrorCodes.BFF_FRAMEWORK_2026, messageParams);
            }
            Object value = info.read(jsonParser, ctxt, null);
            voDefaultValue.getDefaultValue().put(info.getPropertyName(), value);

            jsonParser.nextToken();
        }
        return voDefaultValue;
    }

    protected BffEntityResInfoImpl getCefEntityResInfo() {
        ModelResInfo modelResInfo = manager.getModelInfo();
        BffEntityResInfoImpl resInfo = (BffEntityResInfoImpl) modelResInfo.getCustomResource(modelResInfo.getRootNodeCode());
        if (resInfo == null) {
            throw new BffFrameworkException(ErrorCodes.BFF_FRAMEWORK_2023, modelResInfo.getRootNodeCode());
        }
        return resInfo;
    }

    protected Class getEntityType() {
        return manager.createData().getClass();
    }

    private String getPropertyName(String propertyName) {
        Class entityType = getEntityType();
        if (!propertyName.equals(StringUtils.toCamelCase(propertyName))) {
            return propertyName;
        }

        Method[] methods = entityType.getMethods();
        for (Method method : methods) {
            JsonProperty annotation = method.getAnnotation(JsonProperty.class);
            if (annotation == null)
                continue;
            if (!method.getName().startsWith("get"))
                continue;
            String propName = method.getName().substring(3, method.getName().length());
            if (propertyName.equals(StringUtils.toCamelCase(propName)) || propertyName.equals(propName)) {
                return propName;
            }
        }

        return propertyName;
    }

}
